
import { EntryDelegate } from "./EntryDelegate";
import { AssetManager, Node } from "cc";
import { DEBUG } from "cc/env";
import { HotUpdate } from "../Asset/hotupdate/Hotupdate";
import { Entry } from "./Entry";
import c3d from "../tool/cc";
import UIView from "../Asset/ui/UIView";

declare interface BundleClass<T> {
    new(): T;
    /**@description 当前bundle名 */
    bundle: string;
}
declare type BUNDLE_TYPE = string | import("cc").AssetManager.Bundle;
declare interface EntryClass<T extends Entry> extends BundleClass<T> {
}
declare interface ManagerPrintDelegate<T> {
    print(data: T): void;
}

/**入口管理 */
export class EntryManager {
    private tag = "[EntryManager] : ";
    private _entrys: Map<string, Entry> = new Map();

    /**默认代理，可根据自己项目需要重新实现 */
    public delegate: EntryDelegate = new EntryDelegate();

    private node: Node | null = null;

    /**注册入口 */
    register(entryClass: EntryClass<Entry>) {
        let entry = this.getEntry(entryClass.bundle);
        if (entry) {
            if (DEBUG) {
                c3d.warn(`${this.tag}更新Bundle : ${entryClass.bundle} 入口程序!!!`);
            }
            this._entrys.delete(entryClass.bundle);
        }
        entry = new entryClass;
        entry.bundle = entryClass.bundle;
        this._entrys.set(entry.bundle, entry);
        if (this.node) {
            if (DEBUG) {
                c3d.log(`${this.tag} ${entry.bundle} onLoad`);
            }
            entry.onLoad(this.node);
        }
    }

    onLoad(node: Node) {
        this.node = node;
        this._entrys.forEach((entry, key) => {
            if (!entry.isRunning) {
                entry.onLoad(this.node as Node);
                if (entry.isMain) {
                    if (DEBUG) {
                        c3d.log(`${this.tag}${entry.bundle} onEnter`);
                    }
                    //启动主程序入口
                    entry.onEnter();
                }
            }
        });
    }

    onDestroy(node: Node) {
        this._entrys.forEach((entry) => {
            entry.onDestroy();
        });
    }

    /**主包检测更新 */
    onCheckUpdate() {
        this.delegate.onCheckUpdate();
    }

    call(bundle: BUNDLE_TYPE, eventName: string, ...args: any[]) {
        let entry = this.getEntry(bundle);
        if (entry) {
            entry.call(eventName, args);
        }
    }

    /**
     * 进入bundle,默认代理没办法满足需求的情况，可自行定制 
     * @param bundle bundle
     * @param isQuitGame 是否退出游戏，bundel为主包时有效果
     **/
    enterBundle(bundle: BUNDLE_TYPE, isQuitGame: boolean = false) {
        let config = this.delegate.getEntryConfig(bundle);
        if (config) {
            if (isQuitGame) {
                let entry = this.getEntry(bundle);
                this.delegate.onQuitGame(entry);
            } else {
                GM.assetMgr.bundl.enterBundle(config, this.delegate);
            }
        }
    }

    /**加载bundle完成 */
    onLoadBundleComplete(versionInfo: HotUpdate.BundleConfig, bundle: AssetManager.Bundle) {
        //通知入口管理进入bundle
        let entry = this.getEntry(versionInfo.bundle);
        if (entry) {
            entry.onEnter();
        }
    }

    /**进入GameView完成，卸载除了自己之外的其它bundle */
    onEnterGameView(bundle: BUNDLE_TYPE, gameView: UIView) {
        let entry = this.getEntry(bundle);
        if (entry) {
            entry.onEnterGameView(gameView);
        }
        this.delegate.onEnterGameView(entry, gameView);
    }

    /**管理器调用show时,在GameView的onLoad之后  */
    onShowGameView(bundle: BUNDLE_TYPE, gameView: UIView) {
        let entry = this.getEntry(bundle);
        if (entry) {
            entry.onShowGameView(gameView);
        }
        this.delegate.onShowGameView(entry, gameView);
    }

    /**bundle管事器卸载bundle前通知 */
    onUnloadBundle(bundle: BUNDLE_TYPE) {
        let entry = this.getEntry(bundle);
        if (entry) {
            entry.onUnloadBundle();
        }
    }

    onDestroyGameView(bundle: BUNDLE_TYPE, gameView: UIView) {
        let entry = this.getEntry(bundle);
        if (entry) {
            entry.onUnloadBundle();
            entry.onDestroyGameView(gameView);
        }
    }

    /**获取bundle入口 */
    getEntry(bundle: BUNDLE_TYPE) {
        let name = GM.assetMgr.bundl.getBundleName(bundle);
        let entry = this._entrys.get(name)
        if (entry) {
            return entry;
        }
        return null;
    }

    print(delegate: ManagerPrintDelegate<Entry>) {
        if (delegate) {
            this._entrys.forEach((data) => {
                delegate.print(data);
            });
        }
    }
}